package com.databaseconnectionmobilapi.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.databaseconnectionmobilapi.constant.APIConstant;
import com.databaseconnectionmobilapi.domain.dto.*;
import com.databaseconnectionmobilapi.domain.entity.FieldEntity;
import com.databaseconnectionmobilapi.domain.vo.SelectConnectionVO;
import com.databaseconnectionmobilapi.domain.entity.DatabaseEntity;
import com.databaseconnectionmobilapi.domain.vo.SelectTableFieldVO;
import com.databaseconnectionmobilapi.domain.vo.SelectTableVO;
import com.databaseconnectionmobilapi.mapper.DatabaseMapper;
import com.databaseconnectionmobilapi.service.ConnectionDbService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.databaseconnectionmobilapi.service.RedisService;
import com.databaseconnectionmobilapi.service.mysql.MysqlOpService;
import com.databaseconnectionmobilapi.util.result.RestResult;
import com.databaseconnectionmobilapi.util.util.DbUtil;
import com.databaseconnectionmobilapi.util.util.StringUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author fall
 * @since 2022-01-17
 */
@Service
@AllArgsConstructor
public class ConnectionDbServiceImp extends ServiceImpl<DatabaseMapper, DatabaseEntity> implements ConnectionDbService {
    private DatabaseMapper connectionDbMapper;
    private RedisService redisService;
    private MysqlOpService mysqlOpService;

    @Override
    public RestResult addMysqlConnection(Integer userId, AddMysqlConnectionDTO addMysqlConnectionDTO) {
        DatabaseEntity connectionDbEntity = DatabaseEntity
                .builder()
                .userId(userId)
                .ip(addMysqlConnectionDTO.getConnectionIP())
                .account(addMysqlConnectionDTO.getConnectionAccount())
                .name(addMysqlConnectionDTO.getConnectionName())
                .password(addMysqlConnectionDTO.getConnectionPassword())
                .port(addMysqlConnectionDTO.getPort())
                .type(0)
                .cover("")
                .build();

        save(connectionDbEntity);

        return APIConstant.REST_RESULT_BUILDER.success();
    }

    @Override
    public RestResult selectAllConnection(String token, SelectAllConnectionDTO selectAllConnectionDTO) {
        Page<DatabaseEntity> page = new Page<>(selectAllConnectionDTO.getPage(), selectAllConnectionDTO.getPageSize());
        QueryWrapper<DatabaseEntity> queryWrapper = new QueryWrapper<>();

        Integer userId = StringUtil.getUserId(redisService.get(token, String.class));

        queryWrapper
                .select("id", "name", "ip", "port", "cover", "type")
                .eq("user_id", userId)
                .orderByDesc("times");
        List<DatabaseEntity> connectionDbEntities = connectionDbMapper.selectPage(page, queryWrapper).getRecords();

        return APIConstant.REST_RESULT_BUILDER.success(connectionDbEntities);
    }

    @Override
    public RestResult selectConnection(SelectConnectionDTO selectConnectionDTO) {
        DatabaseEntity connectionDbEntity = connectionDbMapper.selectById(selectConnectionDTO.getId());

        switch (connectionDbEntity.getType()) {
            case 0:
                mysqlOpService.establishMySQLConnection(connectionDbEntity.getId());
                break;
        }

        // 增加一次使用记录
        connectionDbEntity.setTimes(connectionDbEntity.getTimes() + 1);

        updateById(connectionDbEntity);

        return APIConstant.REST_RESULT_BUILDER.success();
    }

    @Override
    public RestResult addConnection(String token, AddConnectionDTO addConnectionDTO) {
        Integer userId = StringUtil.getUserId(redisService.get(token, String.class));

        if (save(DatabaseEntity
                .builder()
                .account(addConnectionDTO.getAccount())
                .password(addConnectionDTO.getPassword())
                .ip(addConnectionDTO.getIp())
                .name(addConnectionDTO.getName())
                .type(addConnectionDTO.getType())
                .port(addConnectionDTO.getPort())
                .userId(userId)
                .cover("")
                .updateTime(LocalDateTime.now())
                .createTime(LocalDateTime.now())
                .build())) {
            return APIConstant.REST_RESULT_BUILDER.success();
        } else {
            return APIConstant.REST_RESULT_BUILDER.fail();
        }
    }

    @Override
    public RestResult delConnection(DelConnectionDTO delConnectionDTO) {
        if (connectionDbMapper.deleteById(delConnectionDTO.getId()) == 0) {
            return APIConstant.REST_RESULT_BUILDER.fail();
        }
        return APIConstant.REST_RESULT_BUILDER.success();
    }

    @Override
    public RestResult deleteConnection(DeleteConnectionDTO deleteConnectionDTO) {
        if (connectionDbMapper.deleteById(deleteConnectionDTO.getId()) != 0) {
            return APIConstant.REST_RESULT_BUILDER.success();
        }

        return APIConstant.REST_RESULT_BUILDER.fail();
    }

    @Override
    public RestResult closeConnection(CloseConnectionDTO closeConnectionDTO) {
        DbUtil.freeMySQLConnection(closeConnectionDTO.getId());

        return APIConstant.REST_RESULT_BUILDER.success();
    }

    @Override
    public RestResult selectAllTable(SelectAllTableDTO selectAllTableDTO) {
        return APIConstant.REST_RESULT_BUILDER.success(DbUtil.selectAllTable(selectAllTableDTO.getId(), selectAllTableDTO.getName()));
    }

    @Override
    public RestResult selectTable(SelectTableDTO selectTableDTO) {
        List<Object> list = (List<Object>) DbUtil.selectTable(selectTableDTO.getId(), selectTableDTO.getDbName(), selectTableDTO.getTableName(),
                selectTableDTO.getPage(), selectTableDTO.getPageSize());

        List<SelectTableFieldVO> selectTableFieldVOS = new ArrayList<>();

        for (FieldEntity fieldEntity : (List<FieldEntity>) list.get(0)) {
            selectTableFieldVOS.add(SelectTableFieldVO
                    .builder()
                    .title(fieldEntity.getName())
                    .dataIndex(fieldEntity.getName())
                    .key(fieldEntity.getName())
                    .type(fieldEntity.getType())
                    .build());
        }

        SelectTableVO selectTableVO = SelectTableVO
                .builder()
                .fieldName(selectTableFieldVOS)
                .data((List<Map<String, Object>>) list.get(1))
                .build();

        return APIConstant.REST_RESULT_BUILDER.success(selectTableVO);
    }

    @Override
    public RestResult selectAllCharset(SelectAllCharsetDTO selectAllCharsetDTO) {
        return APIConstant.REST_RESULT_BUILDER.success(DbUtil.selectAllCharset(selectAllCharsetDTO.getId()));
    }

    @Override
    public RestResult selectAllCollation(SelectAllCollationDTO selectAllCollationDTO) {
        return APIConstant.REST_RESULT_BUILDER.success(DbUtil.selectAllCollection(selectAllCollationDTO.getId(), selectAllCollationDTO.getCharset()));
    }

    @Override
    public RestResult createDb(CreateDbDTO createDbDTO) throws SQLException {
        DbUtil.createDb(createDbDTO.getId(), createDbDTO.getDbName(), createDbDTO.getCharset(), createDbDTO.getCollation());
        return APIConstant.REST_RESULT_BUILDER.success();
    }

    @Override
    public RestResult deleteDb(DeleteDbDTO deleteDbDTO) throws SQLException {
        DbUtil.deleteDb(deleteDbDTO.getId(), deleteDbDTO.getDbName());
        return APIConstant.REST_RESULT_BUILDER.success();
    }

    @Override
    public RestResult updateDb(UpdateDbDTO updateDbDTO) throws SQLException {
        DbUtil.updateDb(updateDbDTO.getId(), updateDbDTO.getDbName(), updateDbDTO.getCharset(), updateDbDTO.getCollation());
        return APIConstant.REST_RESULT_BUILDER.success();
    }

    @Override
    public RestResult selectTableStruct(SelectTableStructDTO selectTableStructDTO) {
        return APIConstant.REST_RESULT_BUILDER.success(DbUtil.selectTableStruct(selectTableStructDTO.getId(), selectTableStructDTO.getName(), selectTableStructDTO.getTableName()));
    }

    @Override
    public RestResult createTable(CreateTableDTO createTableDTO) {
        DbUtil.createTable(createTableDTO.getId(), createTableDTO.getDbName(), createTableDTO.getTableName(), createTableDTO.getList());
        return APIConstant.REST_RESULT_BUILDER.success();
    }

    @Override
    public RestResult addData(AddDataDTO addDataDTO) {
        DbUtil.addData(addDataDTO.getId(), addDataDTO.getDbName(), addDataDTO.getTableName(), addDataDTO.getData());
        return APIConstant.REST_RESULT_BUILDER.success();
    }

    @Override
    public RestResult testConnection(TestConnectionDTO testConnectionDTO) {
        switch (testConnectionDTO.getType()) {
            case 0:
                if (DbUtil.testMysqlConnection(testConnectionDTO.getIP(), testConnectionDTO.getPort(), testConnectionDTO.getAccount(), testConnectionDTO.getPassword())) {
                    return APIConstant.REST_RESULT_BUILDER.success();
                }
                break;
        }
        return APIConstant.REST_RESULT_BUILDER.fail("连接失败");
    }
}
